/**
 * @brief modbus采集器实现模块.这个模块可以采用
 * @version 1.0
 * @date 2018-2-28
 * @author 宋炜
*/
#ifndef MODBUS_HPP
#define MODBUS_HPP
#include "config.hpp"

#if ENABLE_MODBUS == 1
#include <memory>
#include <vector>
#include <atomic>

#include "timer.hpp"
#include "filterio.h"
#include "crc.hpp"
#include "timer.hpp"
#include "modbus_setting.hpp"

class modbus : public filterIO
{
public:
	static const int  WAITING;
	static const int  SENDED;
	static const int  OVERTIME;
	static const int  CANCELED;
	static const int  FINISH;
	static const int  READY;

	struct mission{
		unsigned char       cmd[ 20 ];               // modbus 命令串
		int                 cmd_len;                 // 命令串长度
		std::atomic< int >  trig;                    // 指令状态，分别为等候，发送，超时，临时取消，和完成
		int                 overtime_count;          // 超时次数

		CTimer              timer;                   // 采集频率定时器
		/**
		 * @brief 构造
		 */
		mission( const ModbusSetting::stItem & m );
		~mission();
		/**
		 * @brief
		 */
		mission( const mission& b );
		/**
		 */
		operator bool();
		/**
		 */
		bool operator ==( const mission& b );
		/**
		 */
		mission& operator =( const mission& b );
		/**
		 */
		bool IsReady();
		bool IsOverTime();
		bool IsCancel( int maxCount );
		bool IsWaiting();
		bool IsFinish();
	};

	typedef std::vector< mission >  mList_t;
	typedef mList_t::iterator  mListIt_t;

	long                    default_modbus_overtime;
private:
	mList_t                 m_missions;             // 

	std::atomic< size_t >   m_cur;                  // 当前正在运行的任务
	std::atomic< int >      m_overtime_max_count;   // 最大重发次数。如果某一个任务重发的次数超过了最大次数，则将这个任务取消    
	std::atomic<bool>       m_is_reading;           // 是否正在采样
	CTimer                  m_com_overtime;         // 通讯超时
	CTimer                  m_timer;                // 采集事件循环，按照一定的周期检查所有任务的状态。
	// 并按照不同状态执行对应操作。
public:
	/**
	 * @brief 构造函数。构建一个modbus过滤器
	 * @param overtime,
	 * @param intval,
	 * @param type,
	 * @param l
	 */
	modbus(long overtime , long intval ,io_type type , filterList * l );
	virtual ~modbus();
	/**
	 * @brief 读取任务数量
	 */
	size_t count(){ return m_missions.size(); }
	/**
	 * @brief 启动Modbus采集操作
	 */
	void run()
	{ 
		for( auto i = m_missions.begin(); i != m_missions.end(); i ++ ){
			i ->timer.Start( -1 , true );
		}
		m_timer.Start( -1, true );
	}
	/**
	 * @brief 判断采集任务是否在进行。
	 * @return 如果采集正在进行则返回true，否则返回false
	 */
	bool is_runing(){ return m_timer.IsRuning(); }
	/**
	 * @brief 设置任务间隔
	 * @param intval ， 任务间隔数据单位是ms
	 */
	void interval( long intval ){ m_timer( intval ); }
	/**
	 * @brief 读取采集任务间隔时间。
	 * @return 返回时间
	 */
	long interval(){ return m_timer(); }
private:
	bool on_forward( size_t len , const char * date , err_code &err , size_t& rlen , char ** rd );
	bool on_backward( size_t len , const char * data , err_code &err , size_t& rlen , char ** rd  );
	/**
	 * @brief 执行任务轮询。这个函数的主要任务是，检查已经可以可以发送的任务，将可以发送的任务的命令通过
	 * 串口发送出去。
	 */
	void do_cycle();
};
#endif
#endif // MODBUS_HPP
